package com.uh.rds.testing.validator.types;

import com.uh.rds.testing.validator.DataValidatorBase;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class ListDataValidator extends DataValidatorBase {

    @Override
    public String getType() {
        return "List";
    }

    @Override
    public void process() {
        if (!processJedis.isConnected()) processJedis.connect();
        Random random = new Random();
        processBeginLog();
        for (Map.Entry<String, List<String[]>> listEntity : data.entrySet()) {
            String key = listEntity.getKey();
            boolean succeed = true;
            Object[] listValues = listEntity.getValue().toArray();
            boolean insertReversed = random.nextBoolean();

            if(insertReversed) {
                // 插入到列表的头部，则使用 LPUSH
                for(int i = listValues.length - 1;  i >= 0; i--) {
                    if(processJedis.lpush(key, ((String[]) listValues[i])[0]) <=0) {
                        logger.error("{} key[{}] value[{}] insert(LPUSH) failed!", getName(), key, ((String[]) listValues[i])[0]);
                        succeed = false;
                    }
                }
            }
            else {
                // 插入到列表的尾部，则使用 RPUSH
                for (int i = 0; i < listValues.length; i++) {
                    if(processJedis.rpush(key, ((String[]) listValues[i])[0]) <=0) {
                        logger.error("{} key[{}] value[{}] insert(RPUSH) failed!", getName(), key, ((String[]) listValues[i])[0]);
                        succeed = false;
                    }
                }
            }

            processingLog(succeed);
        }

        processEndLog();
    }

    @Override
    public long expire(int expireSeconds) {
        return super.expire(processJedis, data.keySet(), expireSeconds);
    }

    public boolean validateExpired() {
        return super.validateExpired(validateJedis, data.keySet());
    }

    @Override
    public boolean validate() {
        if (!validateJedis.isConnected()) validateJedis.connect();

        validateBeginLog();

        Collection<String> keys = arguments.isValidateReversed() ? reversedKeys : data.keySet();
        for(String key : keys) {
            boolean keyMatched = true;
            List<String[]> value = data.get(key);
            long listLen = value.size();
            long actualListLen = validateJedis.llen(key);
            if (actualListLen != listLen) {
                keyMatched = false;
                logger.error("{} key[{}] validate failed! Expected size:{} Actual size:{}", getName(),  key, listLen, actualListLen);
            }


            for (int i = 0; i < listLen; i++) {
                String actualSubVal = validateJedis.lindex(key, i);
                String[] expectedSubVal = value.get(i);
                if (! expectedSubVal[0].equals(actualSubVal) ) {
                    keyMatched = false;
                    logger.error("{} key[{}] validate failed! Expected value:{} Actual value:{}", getName(), key, expectedSubVal[0], actualSubVal);
                }
            }

            validatingLog(keyMatched);
        }

        return validateEndLog();
    }

    @Override
    public long clear() {
        return clear(processJedis, validateJedis, data.keySet());
    }
}
